1. Field of the Invention
This invention relates to memory protection in computing devices and more particularly relates to protecting memory according to the current code execution point.
2. Description of the Related Art
In the early days of computing devices, only one program ran on a computer at a time. The running program had complete control over the hardware in the machine including the logic devices, the processor, memory, input devices and output devices. Bugs in the running program could cause the running program to operate incorrectly or to terminate. However, no other programs were affected since only one program ran at a time.
As computers became more complex, multiple programs ran on a single computer. A multitasking kernel regulated access to the processor in various ways. In a common multitasking implementation, the kernel schedules each program running on the computer for a short time slice. One program runs during each time slice. At the end of each time slice, the kernel saves the state of the current running program and then restores the state of a suspended program and allows the suspended program to run during a new time slice. With time slices on the order of milliseconds, the computer is able to run multiple programs serially while giving the impression that the programs are running simultaneously.
In early multitasking environments, each program had complete control of the computer during its time slice. The current running program had control over the processor, the memory, the input devices and the output devices. The current running program had the ability to affect memory allocated to suspended programs. A word processor program had the ability to modify memory assigned to an accounting program. Even though software programmers tried to avoid such mistakes, they did happen and caused many problems. Memory accesses by one program into the memory assigned to another program were common and particularly difficult to detect.
In response to these problems, computer architects and software designers worked together to design process-based protected memory systems. In a process-based protected memory system, the kernel runs programs in processes. The kernel allocates memory to programs on a process basis.
For example, the kernel starts a program in a process. The kernel schedules the process to run and allocates time slices in which the process runs. When the program is the current running process, it requests a block of memory from the kernel. The kernel then allocates a block of memory and associates the memory block with the specific process.
The kernel, in conjunction with dedicated hardware, monitors memory accesses by the running process. Accesses by the running process to memory currently assigned to the running process are allowed. However, accesses by the running process to memory not assigned to the running process create an exception. The kernel handles the exception and prevents the access to memory not allocated to the current process.
The process-based protected memory system achieves its purpose—preventing concurrent running programs from affecting computer resources allocated to other programs. However, it achieves its purpose at a price. First, the amount of time required to switch from one process to another increases. Second, the process switches must happen more frequently in order to handle inter-process communication (IPC). Third, requests of the kernel for computer resources must be regulated either by a process switch or by a system interrupt, creating switching overhead and tying up critical kernel resources.
The kernel must keep track of the memory blocks and permissions assigned to each process. Typically, the kernel uses a page table for each process to store this information. The page table maintains a mapping of virtual addresses used by the running process to physical memory locations. It also tracks which memory has been swapped to disk. The page table for a single process may be quite large. Many computer systems utilize a translation look-aside buffer (TLB) to cache the page table to accelerate address translations.
Process switching is a time-consuming process. When a process is scheduled by the kernel, the kernel flushes the TLB and sets a pointer to the new page table. Parts of the page table may have to be loaded into memory, and additional memory pages associated with the process including code pages and data pages may have to be loaded into memory. By allocating memory to processes in this way, the kernel is able to restrict inter-process memory accesses. However, even simple calls from one process to another incur a process switch overhead.
Exceptions to the process-based protected memory system exist in order to allow the kernel and highly trusted programs to access all memory in the computer. For instance, the kernel normally runs in a privileged mode which allows it to access any memory address without causing an exception. In addition, certain device drivers and shared libraries may run at a privileged level as well. These exceptions reduce the number of required process switches, but also decrease system stability.
Many proposals have been made to reduce the size of kernel code and push as many system level services as possible into non-kernel applications. This type of system is sometimes referred to as a microkernel. An operating system based on a microkernel separates many system functions from the kernel. These separated system functions may exist in system code segments or in separate processes.
If the separated system functions exist as system code segments, then they must be called by non-trusted processes. Under a process-based memory protection architecture, such a design would allow non-trusted programs to directly call system code, bypassing memory protection standards. Alternatively, the system functions may be implemented as separate processes which will service requests from non-trusted processes. However, creating additional processes to carry out system functions will create high overhead costs associated with process switches.
From the foregoing discussion, it should be apparent that a need exists for an apparatus, system, and method that allow applications running on a computing device to directly call system functions without incurring process switching overheads while maintaining memory protection standards to prevent non-trusted applications from accessing system resources inappropriately. Beneficially, such an apparatus, system, and method would increase system stability while reducing the time required to call system functions. Such an apparatus, system and method would also reduce the overhead associated with inter-process communication.